//
//  PHPhotoLibrary+PhotoAsset.swift
//  
//
//  kudos to ricardopereira
//  https://gist.github.com/ricardopereira
//

import Foundation
import Photos

public extension PHPhotoLibrary {
    
    
    typealias PhotoAsset = PHAsset
    typealias PhotoAlbum = PHAssetCollection
    
    static func saveImage(_ image: UIImage, albumName: String, completion: @escaping (PHAsset?)->()) {
        if let album = self.findAlbum(albumName) {
            self.saveImage(image, album: album, completion: completion)
            return
        }
        createAlbum(albumName) { album in
            if let album = album {
                self.saveImage(image, album: album, completion: completion)
            }
            else {
                assert(false, "Album is nil")
            }
        }
    }
    
    static func saveVideo(_ videoUrl: URL, albumName: String, completion: @escaping (PHAsset?)->()) {
        if let album = self.findAlbum(albumName) {
            saveVideo(videoUrl, album: album, completion: completion)
            return
        }
        createAlbum(albumName) { album in
            if let album = album {
                self.saveVideo(videoUrl, album: album, completion: completion)
            }
            else {
                assert(false, "Album is nil")
            }
        }
    }
    
    static fileprivate func saveImage(_ image: UIImage, album: PhotoAlbum, completion: @escaping (PHAsset?)->()) {
        var placeholder: PHObjectPlaceholder?
        PHPhotoLibrary.shared().performChanges({
            // Request creating an asset from the image
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            // Request editing the album
            
            guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album) else {
                assert(false, "Album change request failed")
                return
            }
            // Get a placeholder for the new asset and add it to the album editing request
            guard let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else {
                assert(false, "Placeholder is nil")
                return
            }
            placeholder = photoPlaceholder
            let enumeration: NSArray = [photoPlaceholder]
            albumChangeRequest.addAssets(enumeration)
            
            }, completionHandler: { success, error in
                guard let placeholder = placeholder else {
                    assert(false, "Placeholder is nil")
                    completion(nil)
                    return
                }
                
                if success {
                    completion(PHAsset.ah_fetchAssetWithLocalIdentifier(placeholder.localIdentifier, options:nil))
                }
                else {
                    print(error?.localizedDescription)
                    completion(nil)
                }
        })
    }
     
    static fileprivate func saveVideo(_ videoUrl: URL, album: PhotoAlbum, completion: @escaping (PHAsset?)->()) {
    
        var placeholder: PHObjectPlaceholder?
        
        PHPhotoLibrary.shared().performChanges({
            
            // Request creating an asset from the image
            let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoUrl as URL)
            // Request editing the album
            guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album) else {
                assert(false, "Album change request failed")
                return
            }
            
            // Get a placeholder for the new asset and add it to the album editing request
            guard let videoPlaceholder = createAssetRequest!.placeholderForCreatedAsset else {
                assert(false, "Placeholder is nil")
                return
            }
            
            placeholder = videoPlaceholder
           let enumeration: NSArray = [videoPlaceholder]
            albumChangeRequest.addAssets(enumeration)
            }, completionHandler: { success, error in
                guard let placeholder = placeholder else {
                    assert(false, "Placeholder is nil")
                    completion(nil)
                    return
                }
                
                if success {
                    completion(PHAsset.ah_fetchAssetWithLocalIdentifier(placeholder.localIdentifier, options:nil))
                }
                else {
                    print(error?.localizedDescription)
                    completion(nil)
                }
        })
    
        
    }


    
    static func findAlbumPhoto(_ albumName:String, completion: @escaping (_ image:UIImage?,_ date:Date?)->()) {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
        let collectionResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: fetchOptions)
        guard let photoAlbum = collectionResult.firstObject else {
            completion(nil,nil)
            return
        }
        let assetsResult = PHAsset.fetchAssets(in: photoAlbum, options: nil)
        var assets = Array<PHAsset>()
        
        assetsResult.enumerateObjects({ (asset, index, stop) in
            assets.append(asset)
        })
        
        let requestOptions = PHImageRequestOptions()
        let manager = PHImageManager.default()
        
       
        
        //var img:UIImage?
        for asset in assets {
            manager.requestImage(for: asset , targetSize:PHImageManagerMaximumSize , contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: { (image, infor) in
                completion(image,asset.creationDate!)
               
            })
            
        }
    
    }
    
    static func findAlbum(_ albumName: String) -> PhotoAlbum? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
        let fetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: fetchOptions)
        
        
        
        
        
        guard let photoAlbum = fetchResult.firstObject else {
            return nil
        }
        return photoAlbum
    }
    
    static func createAlbum(_ albumName: String, completion: @escaping (PhotoAlbum?)->()) {
        var albumPlaceholder: PHObjectPlaceholder?
        PHPhotoLibrary.shared().performChanges({
            // Request creating an album with parameter name
            let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
            // Get a placeholder for the new album
            albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
            }, completionHandler: { success, error in
                guard let placeholder = albumPlaceholder else {
                    assert(false, "Album placeholder is nil")
                    completion(nil)
                    return
                }
                
                let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
                guard let album = fetchResult.firstObject else {
                    assert(false, "FetchResult has no PHAssetCollection")
                    completion(nil)
                    return
                }
                
                if success {
                    completion(album)
                }
                else {
                    print(error?.localizedDescription)
                    completion(nil)
                }
        })
    }
    
    static func loadThumbnailFromLocalIdentifier(_ localIdentifier: String, completion: @escaping (UIImage?)->()) {
        guard let asset = PHAsset.ah_fetchAssetWithLocalIdentifier(localIdentifier, options:nil) else {
            completion(nil)
            return
        }
        loadThumbnailFromAsset(asset, completion: completion)
    }
    
    static func loadThumbnailFromAsset(_ asset: PhotoAsset, completion: @escaping (UIImage?)->()) {
        PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .aspectFit, options: PHImageRequestOptions(), resultHandler: { result, info in
            completion(result)
        })
    }
    
}

